package com.xb.system.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xb.model.domain.Users;
import com.xb.system.mapper.db0.DistinctUserMapper;
import com.xb.system.mapper.db0.UsersMapper;
import com.xb.system.service.UsersService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * (Users)表服务实现类
 */
@Service
@Slf4j
public class UsersServiceImpl extends ServiceImpl<UsersMapper, Users> implements UsersService {
    @Resource
    private UsersMapper usersMapper;
    
    @Resource
    private DistinctUserMapper distinctUserMapper;

//    public boolean checkUserMatch(String phone, String username) {
//        //先去分表中查询，查不到再去distinct_user表中查询
//        if (usersMapper.checkUserMatch(phone, username) > 0) {
//            return true;
//        } else return distinctUserMapper.checkUserMatch(phone, username) > 0;
//    }
    public boolean checkUserMatch(String phone, String username) {
        try {
            if (phone == null || username == null || phone.equals("无")) {
                log.warn("检查用户匹配失败: phone={}, username={} - 参数无效", phone, username);
                return false;
            }
            
            // 清理电话号码：去除所有非数字字符，确保查询格式一致
            String cleanPhone = phone.replaceAll("[^\\d]", "");
            log.info("开始检查用户匹配: 原始phone={}, 清理后phone={}, username={}", phone, cleanPhone, username);
            
            // 快速定位：根据Python脚本的MurmurHash3算法计算表索引
            int tableIndex = getTableIndexByMurmurHash3(cleanPhone);
            String targetTable = "data_" + tableIndex;
            
            log.info("phone={} 根据MurmurHash3计算得到表索引: {}, 目标表: {}", cleanPhone, tableIndex, targetTable);
            
            // 只查询目标表，使用清理后的号码
            List<Map<String, Object>> matches = usersMapper.checkUserMatchSingleTable(cleanPhone, username, targetTable);
            
            if (!matches.isEmpty()) {
                Map<String, Object> record = matches.get(0);
                String recordName = (String) record.get("name");
                
                log.info("找到匹配用户: phone={}, username={}, recordName={}, 在表{}中匹配成功", 
                        phone, username, recordName, targetTable);
                return true;
            }
            
            log.info("未找到匹配用户: phone={}, username={}, 在表{}中未找到", phone, username, targetTable);
            return false;
        } catch (Exception e) {
            log.error("检查用户匹配失败: phone={}, username={}", phone, username, e);
            return false; // 异常情况下返回 false，避免中断流程
        }
    }
    
    /**
     * 使用MurmurHash3算法计算表索引（与Python脚本保持一致）
     */
    private int getTableIndexByMurmurHash3(String phone) {
        if (phone == null || phone.trim().isEmpty()) {
            return 0;
        }
        
        // 实现MurmurHash3算法（与Python的mmh3.hash()保持一致）
        int hashValue = murmurHash3(phone);
        return Math.abs(hashValue) % 200;
    }
    
    /**
     * MurmurHash3算法实现
     * 与Python的mmh3.hash()算法保持一致
     */
    private int murmurHash3(String key) {
        byte[] data = key.getBytes();
        int length = data.length;
        int seed = 0;
        
        // MurmurHash3常量
        int c1 = 0xcc9e2d51;
        int c2 = 0x1b873593;
        int r1 = 15;
        int r2 = 13;
        int m = 5;
        int n = 0xe6546b64;
        
        int hash = seed;
        int nblocks = length / 4;
        
        // body
        for (int i = 0; i < nblocks; i++) {
            int k = getblock(data, i * 4);
            k *= c1;
            k = rotl32(k, r1);
            k *= c2;
            
            hash ^= k;
            hash = rotl32(hash, r2);
            hash = hash * m + n;
        }
        
        // tail
        int tail = nblocks * 4;
        int k1 = 0;
        switch (length & 3) {
            case 3:
                k1 ^= (data[tail + 2] & 0xff) << 16;
            case 2:
                k1 ^= (data[tail + 1] & 0xff) << 8;
            case 1:
                k1 ^= (data[tail] & 0xff);
                k1 *= c1;
                k1 = rotl32(k1, r1);
                k1 *= c2;
                hash ^= k1;
        }
        
        // finalization
        hash ^= length;
        hash = fmix(hash);
        
        return hash;
    }
    
    private int getblock(byte[] data, int i) {
        return ((data[i] & 0xff) | 
                ((data[i + 1] & 0xff) << 8) | 
                ((data[i + 2] & 0xff) << 16) | 
                ((data[i + 3] & 0xff) << 24));
    }
    
    private int rotl32(int x, int r) {
        return (x << r) | (x >>> (32 - r));
    }
    
    private int fmix(int h) {
        h ^= h >>> 16;
        h *= 0x85ebca6b;
        h ^= h >>> 13;
        h *= 0xc2b2ae35;
        h ^= h >>> 16;
        return h;
    }
    public void createIndexes() {
        log.info("正在创建分表的索引");
        usersMapper.createIndexes();
        log.info("创建分表索引成功，正在创建distinct_user表的索引");
        distinctUserMapper.createIndexes();
        log.info("索引创建成功");
    }
    
    public void dropIndexes() {
        usersMapper.dropIndexes();
        log.info("删除分表索引成功，正在删除distinct_user表的索引");
        distinctUserMapper.dropIndexes();
        log.info("索引删除成功");
    }

    @Override
    public long totalRows() {
        long totalRows = 0;
        for (int i = 0; i < 200; i++) {
            totalRows += usersMapper.totalRows(i);
        }
        return totalRows + distinctUserMapper.selectCount(null);
    }
}

